#pragma once

#include "ImmutableList.h"

#include "GrvNamespaces.h"
#include "GrvTypes.h"
#include "GrvForce.h"
#include "GrvVectorTimeFunction.h"

Meson_Gravitas_Force_BEGIN

struct ForceAccumulatorState;

//------------------------------------------------------------------------------------------
/// \class ForceAccumulator
/// Maintains a number of force generators bound to a body that owns the accumulator, and
/// provides a means of computing the total linear force and torque.
//------------------------------------------------------------------------------------------
class GRAVITAS_API ForceAccumulator
{
private: // private variables
	ForceAccumulatorState *m_pForceAccumulatorState;

public: // public methods
	//------------------------------------------------------------------------------------------
	/// Constructs the force accumulator using the given pointers to a body's mass, kinetic and
	/// geometric properties.
	/// \param p_pMassProperties Pointer to a mass properties structure.
	/// \param p_pKineticProperties Pointer to a kinetic properties structure.
	/// \param p_pGeometry Managed pointer to a geometry implementation.
	//------------------------------------------------------------------------------------------
	ForceAccumulator(
		Meson::Gravitas::Body::MassProperties* p_pMassProperties,
		Meson::Gravitas::Kinetics::KineticProperties* p_pKineticProperties,
		Meson::Gravitas::Geometry::GeometryPtr p_pGeometry);

	//------------------------------------------------------------------------------------------
	/// Destroys the force accumulator.
	//------------------------------------------------------------------------------------------
	~ForceAccumulator(void);

	//------------------------------------------------------------------------------------------
	/// Returns the force generators maintained by the force accumulator.
	/// \returns the force generators maintained by the force accumulator.
	//------------------------------------------------------------------------------------------
	Meson::Common::Collections::TImmutableList<ForcePtr>& GetForces(void) const;

	//------------------------------------------------------------------------------------------
	/// Clears all the force generators maintained by the force accumulator.
	//------------------------------------------------------------------------------------------
	void ClearForces(void);

	//------------------------------------------------------------------------------------------
	/// Clears all the instantaneous force generators maintained by the force accumulator.
	//------------------------------------------------------------------------------------------
	void ClearInstantaneousForces(void);

	//------------------------------------------------------------------------------------------
	/// Adds a force generator to the accumulator.
	/// \param p_pForce A managed pointer to a force generator.
	//------------------------------------------------------------------------------------------
	void AddForce(ForcePtr p_pForce);

	//------------------------------------------------------------------------------------------
	/// Removes the force generator from the accumulator.
	/// \param p_pForce A managed pointer to a force generator.
	//------------------------------------------------------------------------------------------
	void RemoveForce(ForcePtr p_pForce);

	//------------------------------------------------------------------------------------------
	/// Returns a vector time function for the total linear force generated by the accumulator.
	/// \returns a vector time function for the total linear force generated by the accumulator.
	//------------------------------------------------------------------------------------------
	Meson::Gravitas::Kinetics::IVectorTimeFunction& GetForce(void);

	//------------------------------------------------------------------------------------------
	/// Returns a vector time function for the total torque generated by the accumulator.
	/// \returns a vector time function for the total torque generated by the accumulator.
	//------------------------------------------------------------------------------------------
	Meson::Gravitas::Kinetics::IVectorTimeFunction& GetTorque(void);

	//------------------------------------------------------------------------------------------
	/// Returns a vector time function for the total linear acceleration generated by the
	/// accumulator.
	/// \returns a vector time function for the total linear acceleration generated by the
	///          accumulator.
	//------------------------------------------------------------------------------------------
	Meson::Gravitas::Kinetics::IVectorTimeFunction& GetLinearAcceleration(void);

	//------------------------------------------------------------------------------------------
	/// Returns a vector time function for the total angular acceleration generated by the
	/// accumulator.
	/// \returns a vector time function for the total angular acceleration generated by the
	///          accumulator.
	//------------------------------------------------------------------------------------------
	Meson::Gravitas::Kinetics::IVectorTimeFunction& GetAngularAcceleration(void);
};

Meson_Gravitas_Force_END
